using System.Diagnostics;

namespace AOPDemo;

public class OrderServiceProxy
{
    private readonly IOrderService _realService;
    // 虽然除了构造函数不一样，其他都一样，但是两者有本质区别
    // 构造函数没有参数，直接在里面创建了AccountService类
    // 装饰器模式关注于在一个对象上动态添加方法，而代理模式关注于控制对象的访问
    // 使用代理模式的时候，我们常常是在代理类内部去创建一个对象的实例
    // 使用装饰器模式的时候，我们通常是将原始对象作为一个参数传递给装饰器的构造函数
    // 使用代理模式，我们的代理类可以隐藏一个类的具体信息，从外面看不到被代理的类
    // 使用装饰器模式的时候，我们可以明确地知道装饰的是谁
    // 更重要的是，代理类里面是写死的，在编译的时候就确定了关系。而装饰器是在运行时来确定的
    public OrderServiceProxy() =>   _realService = new OrderService();
    public void PlaceOrder(string product)
    {
        // 前置处理（AOP切入点）
        Console.WriteLine($"[代理] 开始下单 {DateTime.Now}");
        var stopwatch = Stopwatch.StartNew();
        try
        {
            // 调用真实方法
            _realService.PlaceOrder(product);
            // 后置处理（成功）
            Console.WriteLine($"[代理] 下单成功，耗时 {stopwatch.ElapsedMilliseconds}ms");
        }
        catch (Exception ex)
        {
            // 异常处理
            Console.WriteLine($"[代理] 下单失败: {ex.Message}");
            throw;
        }
        finally
        {
            // 最终处理
            Console.WriteLine($"[代理] 方法调用结束");
        }
    }
}